from Bases import OSCBaseObject

class BaseWidget(OSCBaseObject):
    _widget_args = ['auth', 'version', 'grid_size', 'grid_pos', 'span']
    def __init__(self, **kwargs):
        self.id = kwargs.get('id')
        self.bank_number = kwargs.get('bank_number')
        kwargs.setdefault('osc_address', str(self.id))
        super(BaseWidget, self).__init__(**kwargs)
        self.namespace = kwargs.get('namespace', 'mrmrIB')
        self.auth = kwargs.get('auth', 'nil')
        self.version = kwargs.get('version', '.1')
        self.grid_size = kwargs.get('grid_size', [4, 4])
        self.grid_pos = kwargs.get('grid_pos', [1, 1])
        self.span = kwargs.get('span', [1, 1])
        wargs = []
        cls = self.__class__
        while cls != OSCBaseObject:
            print cls
            for arg in reversed(getattr(cls, '_widget_args', [])):
                wargs.insert(0, arg)
            cls = cls.__bases__[0]
        self.widget_args = wargs
        
        self.src_object = kwargs.get('src_object')
        self.src_attr = kwargs.get('src_attr')
        self.src_signal = kwargs.get('src_signal')
        if self.src_signal:
            self.src_object.connect(self.src_signal, self.on_src_object_update)
            
        self.add_osc_handler(callbacks={'*':self.on_osc_update})
        
        
    def on_osc_update(self, **kwargs):
        print 'mrmr got:', kwargs
            
    def on_src_object_update(self, **kwargs):
        pass
        
    def build_string(self):
        args = []
        for arg in self.widget_args:
            val = getattr(self, arg)
            if type(val) == list or type(val) == tuple:
                args.extend([str(v) for v in val])
            else:
                args.append(str(val))
        return '/%s %s %s' % (self.namespace, self.widget_name, ' '.join(args))
        

class Button(BaseWidget):
    widget_name = 'pushbutton'
    _widget_args = ['label', 'style']
    def __init__(self, **kwargs):
        self._touch_state = False
        if not hasattr(self, 'osc_touch_method'):
            self.osc_touch_method = self.widget_name
        super(Button, self).__init__(**kwargs)
        self.register_signal('press', 'release')
        self.add_osc_handler(callbacks={self.osc_touch_method:self.on_osc_touch_update})
        self.label = kwargs.get('label', '')
        self.style = kwargs.get('style', 1)
        
    @property
    def touch_state(self):
        return self._touch_state
    
    def on_osc_update(self, **kwargs):
        pass
    
    def on_osc_touch_update(self, **kwargs):
        state = kwargs.get('values')[0] > 0
        if state != self.touch_state:
            self._touch_state = state
            d = {True:'press', False:'release'}
            self.emit(d[state], widget=self)
            print self.widget_name, self.id, d[state]

class Toggle(Button):
    widget_name = 'togglebutton'
    def __init__(self, **kwargs):
        self._state = False
        super(Toggle, self).__init__(**kwargs)
        self.register_signal('state_changed')
        print self.widget_name, self.osc_node._childNodes['*'].get_full_path()
    def on_osc_update(self, **kwargs):
        values = kwargs.get('values')
        self.emit('press', widget=self)
        state = values[0] > 0
        if state != self.state:
            self._state = state
            self.emit('state_changed', widget=self, state=state)
            print self.widget_name, self.id, state
        self.emit('release', widget=self)
        
    @property
    def state(self):
        return self._state
    @state.setter
    def state(self, value):
        if value != self._state:
            self._state = value
            self.emit('state_changed', widget=self, state=value)
    
class Slider(BaseWidget):
    widget_name = 'slider'
    _widget_args = ['label']
    def __init__(self, **kwargs):
        self._value = 0.
        super(Slider, self).__init__(**kwargs)
        self.register_signal('value_update')
        self.label = kwargs.get('label', '')
        self.add_osc_handler(address='horizontal', callbacks={'*':self.on_osc_value_update})
        
    @property
    def value(self):
        return self._value
    @value.setter
    def value(self, value):
        if value != self.value:
            #self._value = value
            self.osc_node.send_message(address='horizontal/'+self.widget_name, value=value)
    
    def on_src_object_update(self, **kwargs):
        pass
        
    def on_osc_value_update(self, **kwargs):
        value = kwargs.get('values')[0]
        if value != self.value:
            self._value = value
            self.emit('value_update', widget=self, value=value)
            print self.widget_name, self.id, value

class TextView(BaseWidget):
    widget_name = 'textview'
    _widget_args = ['label']
    def __init__(self, **kwargs):
        super(TextView, self).__init__(**kwargs)
        self.label = kwargs.get('label', '')
        
class TitleView(TextView):
    widget_name = 'titleview'
    _widget_args = ['style']
    def __init__(self, **kwargs):
        super(TitleView, self).__init__(**kwargs)
        self.style = kwargs.get('style', 2)
        
class xyPad(Button):
    widget_name = 'tactilezone'
    pos_keys = ['tactilezone'+key for key in ['X', 'Y']]
    def __init__(self, **kwargs):
        if not hasattr(self, '_pos'):
            self._pos = [0., 0.]
        self.osc_touch_method = 'tactilezoneTouchDown'
        super(xyPad, self).__init__(**kwargs)
        self.register_signal('pos_update', 'press', 'release')
        d = dict(zip(self.pos_keys, [self.on_osc_pos_update] * len(self.pos_keys)))
        self.add_osc_handler(callbacks=d)
        
    @property
    def pos(self):
        return self._pos
        
    def on_osc_update(self, **kwargs):
        pass
            
    def on_osc_pos_update(self, **kwargs):
        method = kwargs.get('method')
        value = kwargs.get('values')[0]
        i = self.pos_keys.index(method)
        if value != self._pos[i]:
            self._pos[i] = value
            self.emit('pos_update', widget=self, pos=self.pos)
            print self.widget_name, self.id, i, value
        
class xyzPad(xyPad):
    widget_name = 'tactile3D'
    pos_keys = ['tactile3D'+key for key in ['X', 'Y', 'Z']]
    def __init__(self, **kwargs):
        self._pos = [0.] * 3
        super(xyzPad, self).__init__(**kwargs)
        
widget_classes = (dict(Button=Button, Toggle=Toggle, Slider=Slider, xyPad=xyPad, xyzPad=xyzPad))